<?php

namespace july\julyadmin\builder\traits\actions;

/**
 * 下拉数据源
 */
trait HasSelectPage
{
    /**
     * 下拉列表默认查询条件，如 [['disabled', '=', 1]]，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
     * @param array
     */
    protected $selectWhere = [];

    /**
     * 下拉列表模糊查询字段,如 'name|title'，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin，当前表可以不加
     * @param string
     */
    protected $selectSearch = '';

    /**
     * 下拉列表默认 Text 字段 如 'id#nickname'或者'id:{id}-名称:{name}'，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin，当前表可以不加
     * @param string
     */
    protected $selectTextField = '';

    /**
     * 下拉默认id字段,如：id
     * @param string
     */
    protected $selectIdField = '';

    /**
     * 下拉列表查询时的字段，如：id,name，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
     * @param string
     */
    protected $selectFields = '*';

    /**
     * 下拉join关联查询的表信息如，['category'=>'inner','comment'=>'left']
     * @var array
     */
    protected $selectRelationWithJoins = [];
    /**
     * 下拉with预查询关联表信息，如category,comment
     * @var array
     */
    protected $selectRelationWiths = [];

    /**
     * 下拉列表父id字段，如：parent_id，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin，当前表可以不加
     * @var string
     */
    protected $selectParentId = 'parent_id';

    /**
     * 下拉列表查询第一层数据列表条件，如[['parent_id','=',0]],当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候首次查询最父层的数据列表可能需要传入这个参数，如果有配置了$this->SelectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
     * @var [type]
     */
    protected $selectOneParentWhere = [['parent_id', '=', 0]];

    /**
     * 下拉列表查询排序，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
     * @param string
     */
    protected $selectOrder = 'id DESC';

    /**
     * 加载下拉列表
     * @param  integer $page     第几页
     * @param  integer $rows     每页多少条
     * @param  string  $keyword  搜索关键字
     * @param  string  $parent_id  如果父组件是多选，这里的值会是多个英文逗号连接的字符串
     * @param  array   $default  默认值
     * @return json
     */
    public function selectPage($page = 1, $rows = 10, $keyword = '', $parent_id = '', $default = [])
    {
        $page = $page < 1 ? 1 : $page;

        $where = !$default ? $this->selectWhere : [];

        $where = $this->filterSelectPageWhere($where);

        if (!$this->selectTextField && $this->selectSearch) {
            $this->selectTextField = explode('|', $this->selectSearch);
        }

        $pk = $this->selectIdField ?: $this->getPk();
        if ($keyword) {
            if ($this->selectSearch) {
                $where[] = [$this->selectSearch, 'like', '%' . $keyword . '%'];
            }
        }

        //如果有需要关联的表，就判断id有没有添加前缀，没有就加上当前表名作为前缀
        if ($this->relationWithJoins && $this->selectRelationWithJoins) {
            $pk = array_filter(explode('.', $pk));
            if (count($pk) == 1) {
                $table_name = str_replace(config('database.connections.mysql.prefix'), '', $this->dataModel->getTable());
                array_unshift($pk, $table_name);
                $pk = implode('.', $pk);
            }
        }

        if ($default) {
            $default = array_filter($default);
            if ($default) {
                $where[] = [$pk, 'in', $default];
            } else {
                return json(["code" => 1, "total" => 0, "data" => []]);
            }
        }

        $db = $this->dataModel->field($this->selectFields);
        foreach ($this->selectRelationWithJoins as $relation_k => $relation_v) {
            $db = $db->withJoin($relation_k, $relation_v);
        }

        if ($this->tableType == 'table' || $default) {

            $total = $db->with($this->selectRelationWiths)->where($where)->order($this->selectOrder)->count();
            $list  = $db->with($this->selectRelationWiths)->where($where)->order($this->selectOrder)->limit(($page - 1) * $rows, $rows)->select()->toArray();

            foreach ($list as $select_k => &$select_v) {
                if ($this->getPk() != "id") {
                    $select_v["id"] = $select_v[$this->getPk()];
                }
                if (isset($select_v['disabled'])) {
                    unset($select_v['disabled']);
                }
                $select_v["text"] = $this->handleSelectTextField($this->selectTextField, $select_v);
            }
        } else {
            $total = $db->with($this->selectRelationWiths)->where(array_merge($where, !$default ? $this->selectOneParentWhere : []))->count();
            $data  = $db->with($this->selectRelationWiths)->where(array_merge($where, !$default ? $this->selectOneParentWhere : []))->order($this->selectOrder)->limit(($page - 1) * $rows, $rows)->select()->toArray();

            $list = [];
            foreach ($data as $select_k => &$select_v) {
                $parent_id = $select_v[$this->getPk()];
                if ($this->getPk() != "id") {
                    $select_v["id"] = $select_v[$this->getPk()];
                }
                $select_v["text"] = $this->handleSelectTextField($this->selectTextField, $select_v);
                if (isset($select_v['disabled'])) {
                    unset($select_v['disabled']);
                }
                $list[]   = $select_v;
                $children = [];
                $this->getSelectPageTree($parent_id, $where, $children, "├─");
                foreach ($children as $children_k => $children_v) {
                    $list[] = $children_v;
                }
            }
        }
        return json(["code" => 1, "total" => $total, "data" => $list]);
    }

    /**
     * @Author   July
     * @DateTime 2023-10-10T09:26:00+0800
     * @param    integer                  $parent_id    父id
     * @param    array                    $where        查询条件数组
     * @param    array                    &$children    下级数据
     * @param    array                    $childrens    下级数据列表
     * @param    string                   $prefix
     * @return   array                                  返回下拉列表
     */
    private function getSelectPageTree($parent_id = 0, $where = [], &$children = [], $prefix = '', $newPrefix = '')
    {
        $children_where   = [];
        $children_where[] = [$this->selectParentId ?? 'parent_id', '=', $parent_id];
        $db               = $this->dataModel->field($this->selectFields);
        foreach ($this->selectRelationWithJoins as $relation_k => $relation_v) {
            $db = $db->withJoin($relation_k, $relation_v);
        }
        $list = $db->with($this->selectRelationWiths)->where(array_merge($children_where, $where))->order($this->selectOrder)->select()->toArray();
        $newPrefix .= $prefix;
        foreach ($list as $chileren_k => &$arr) {
            $parent_id = $arr[$this->getPk()];
            if ($this->getPk() != "id") {
                $arr["id"] = $arr[$this->getPk()];
            }
            if (isset($arr['disabled'])) {
                unset($arr['disabled']);
            }
            $arr["text"]     = $newPrefix . $this->handleSelectTextField($this->selectTextField, $arr);
            $children[]      = $arr;
            $arr['children'] = $this->getSelectPageTree($parent_id, $where, $children, $prefix, $newPrefix);
        }
        return $list;
    }

    /**
     * 加载树形数据列表
     * @param  string  $parent_id 父id，这里的值会是多个英文逗号连接的字符串
     * @param  string  $default   默认值
     * @return json
     */
    public function selectTree($parent_id = '', $default = '')
    {
        $where = $this->selectWhere;

        $where = $this->filterSelectPageWhere($where);

        if (!$this->selectTextField && $this->selectSearch) {
            $this->selectTextField = explode('|', $this->selectSearch);
        }

        $pk = $this->selectIdField ?: $this->getPk();

        //如果有需要关联的表，就判断id有没有添加前缀，没有就加上当前表名作为前缀
        if ($this->relationWithJoins) {
            $pk = array_filter(explode('.', $pk));
            if (count($pk) == 1) {
                $table_name = str_replace(config('database.connections.mysql.prefix'), '', $this->dataModel->getTable());
                array_unshift($pk, $table_name);
                $pk = implode('.', $pk);
            }
        }

        if ($default) {
            $default = array_filter($default);
            if ($default) {
                $where[] = [$pk, 'in', $default];
            } else {
                return json(["code" => 1, "total" => 0, "data" => []]);
            }
        }

        $db = $this->dataModel->field($this->selectFields);
        foreach ($this->selectRelationWithJoins as $relation_k => $relation_v) {
            $db = $db->withJoin($relation_k, $relation_v);
        }

        if ($this->tableType == 'table' || $default) {
            $total = $db->with($this->selectRelationWiths)->where($where)->order($this->selectOrder)->count();
            $list  = $db->with($this->selectRelationWiths)->where($where)->order($this->selectOrder)->select()->toArray();

            foreach ($list as $select_k => &$select_v) {
                if ($this->getPk() != "id") {
                    $select_v["id"] = $select_v[$this->getPk()];
                }
                if (isset($select_v['disabled'])) {
                    unset($select_v['disabled']);
                }
                $select_v["text"] = $this->handleSelectTextField($this->selectTextField, $select_v);
            }
        } else {
            $total = $db->with($this->selectRelationWiths)->where(array_merge($where, $this->selectOneParentWhere))->count();
            $list  = $db->with($this->selectRelationWiths)->where(array_merge($where, $this->selectOneParentWhere))->order($this->selectOrder)->select()->toArray();

            foreach ($list as $select_k => &$select_v) {
                $parent_id = $select_v[$this->getPk()];
                if ($this->getPk() != "id") {
                    $select_v["id"] = $select_v[$this->getPk()];
                }
                $select_v["text"] = $this->handleSelectTextField($this->selectTextField, $select_v);
                if (isset($select_v['disabled'])) {
                    unset($select_v['disabled']);
                }
                $select_v['children'] = $this->getSelectTree($parent_id, $where);
            }
        }
        return json(["code" => 1, "total" => $total, "data" => $list]);
    }

    /**
     * 获取树形数据列表
     * @Author   July
     * @DateTime 2023-10-10T09:26:00+0800
     * @param    integer                  $parent_id    父id
     * @param    array                    $where        查询条件数组
     * @return   array                                  返回列表
     */
    private function getSelectTree($parent_id = 0, $where = [])
    {
        $children_where   = [];
        $children_where[] = [$this->selectParentId ?? 'parent_id', '=', $parent_id];
        $db               = $this->dataModel->field($this->selectFields);
        foreach ($this->selectRelationWithJoins as $relation_k => $relation_v) {
            $db = $db->withJoin($relation_k, $relation_v);
        }
        $list = $db->with($this->selectRelationWiths)->where(array_merge($children_where, $where))->order($this->selectOrder)->select()->toArray();

        foreach ($list as $chileren_k => &$arr) {
            $parent_id = $arr[$this->getPk()];
            if ($this->getPk() != "id") {
                $arr["id"] = $arr[$this->getPk()];
            }
            if (isset($arr['disabled'])) {
                unset($arr['disabled']);
            }
            $arr["text"]     = $this->handleSelectTextField($this->selectTextField, $arr);
            $arr['children'] = $this->getSelectTree($parent_id, $where);
        }
        return $list;
    }

    /**
     * 处理selectTextField自定义数据格式，可以实现丰富的样式
     * @Author
     * @DateTime 2023-08-07T22:31:42+0800
     * @param    string                  $selectTextField   selectTextField内容
     * @param    array                   $data 表格数据数组
     * @return   array                   $data 处理过后的表格数据列表
     */
    protected function handleSelectTextField($selectTextField = [], $data = [])
    {
        $value = $selectTextField;
        //处理to数据
        if ($selectTextField) {
            $preg = "/\{([a-zA-Z_0-9\.]+)\}/";
            preg_match_all($preg, $selectTextField, $res);
            if (isset($res[1]) && $res[1]) {
                foreach ($res[1] as $field) {
                    if (stripos($field, '.') > -1) {
                        $fields   = array_filter(explode('.', $field));
                        $valueObj = $data;
                        foreach ($fields as $field_key => $field_value) {
                            if (isset($valueObj[$field_value])) {
                                $valueObj = $valueObj[$field_value];
                            }
                        }
                        $tovalue = $valueObj;
                        $value   = str_replace('{' . $field . '}', $tovalue, $value);
                    } else {
                        $tovalue = isset($data[$field]) ? $data[$field] : '';
                        $value   = str_replace('{' . $field . '}', $tovalue, $value);
                    }
                }
            }
        }
        return $value;
    }

    /**
     * 处理下拉列表查询条件
     * @param  array $where  现有的查询条件
     * @return array
     */
    protected function filterSelectPageWhere($where = [])
    {

        return $where;
    }
}
